package com.blr.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * ClassName: SecurityConfig
 * Description:
 * Date: 2022/11/07 PM 10:48:48
 * <p>
 * project: codes
 * package: com.blr.config
 * email: 1085844536@qq.com
 * version:
 *
 * @author WangGuojian
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    public final FindByIndexNameSessionRepository findByIndexNameSessionRepository;

    /**
     * Creates an instance with the default configuration enabled.
     */
    @Autowired
    public SecurityConfig(FindByIndexNameSessionRepository findByIndexNameSessionRepository) {
        this.findByIndexNameSessionRepository = findByIndexNameSessionRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .and()
                .logout()
                .and()
                .csrf().disable()
                // 开启会话管理
                .sessionManagement()
                // 允许会话最大并发只能一个客户端
                .maximumSessions(1)
                // 传统架构下处理方案：当用户的挤下线之后跳转路径
                //.expiredUrl("/login")
                // 前后端分离架构处理方案
                .expiredSessionStrategy(event -> {
                    HttpServletResponse response = event.getResponse();
                    Map<String, Object> result = new HashMap<>(16);
                    result.put("status", 500);
                    result.put("msg", "当前会话已经失效，请重新登录！");
                    String s = new ObjectMapper().writeValueAsString(result);
                    response.setContentType("application/json;charset=utf-8");
                    response.getWriter().println(s);
                    response.flushBuffer();
                })
                // 将 session 交给谁管理
                .sessionRegistry(sessionRegistry())
                // 一旦登录，禁止再次登录
                .maxSessionsPreventsLogin(true);
    }

    /**
     * 创建 session 同步到 redis 中方案
     *
     * @return
     */
    @Bean
    public SpringSessionBackedSessionRegistry sessionRegistry() {
        return new SpringSessionBackedSessionRegistry(findByIndexNameSessionRepository);
    }

    //@Bean
    //public HttpSessionEventPublisher httpSessionEventPublisher() {
    //    return new HttpSessionEventPublisher();
    //}
}
